package be.nvlooy.moviereminder.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSourceAware;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import be.nvlooy.moviereminder.common.SessionMessage;
import be.nvlooy.moviereminder.entities.Friendship;
import be.nvlooy.moviereminder.entities.FriendshipStatus;
import be.nvlooy.moviereminder.entities.User;
import be.nvlooy.moviereminder.exception.ServiceException;
import be.nvlooy.moviereminder.service.FriendshipService;
import be.nvlooy.moviereminder.service.MailService;
import be.nvlooy.moviereminder.service.UserService;

@Controller
@RequestMapping(value="/friends")
public class FriendController extends BasicController implements MessageSourceAware {
	
	private FriendshipService friendshipService;

	private UserService userService;
	
	private MailService mailService;
	
	@Autowired
	public void setFriendshipService(FriendshipService friendshipService) {
		this.friendshipService = friendshipService;
	}
	
	@Autowired
	public void setUserService(UserService userService) {
		this.userService = userService;
	}
	
	@Autowired
	public void setMailService(MailService mailService) {
		this.mailService = mailService;
	}
	
	@RequestMapping
	public String index(
			@RequestParam(value="search", required=false) String search, 
			@RequestParam(value="status", required=false) String status, 
			Model model) {
		
		User user = getAuthenticatedUser();

		FriendshipStatus fsStatus = FriendshipStatus.ACTIVE;
		
		List<Friendship> friendships;
		
		if(search != null && !search.isEmpty())
			friendships = friendshipService.findByName(user, search, fsStatus);
		else if(status != null && !status.isEmpty()) {
			if(status.equals("pendingincoming")) {
				fsStatus = FriendshipStatus.PENDING;
				friendships = friendshipService.getIncomingRequests(user);
			}
			else {
				if(status.equals("pendingoutgoing"))
					fsStatus = FriendshipStatus.PENDING;
				else
					fsStatus = FriendshipStatus.valueOf(status.toUpperCase());
				friendships = friendshipService.getFriendships(user, fsStatus);
			}
		}
		else
			friendships = friendshipService.getFriendships(user, fsStatus);
		
		model.addAttribute("search", search);
		model.addAttribute("status", status);
		model.addAttribute("friends", friendships);
		return "/friends/index";
	}	
	
	@RequestMapping(value="/info/{friendID}")
	public String friendshipInfo(@PathVariable int friendID, Model model) {
		User user = getAuthenticatedUser();
		User friend = userService.findByID(friendID);
		Friendship friendship = friendshipService.getFriendship(user, friend);
		model.addAttribute("friendship", friendship);
		return "/friends/info";
	}
	
	@RequestMapping(value="/block/{friendID}")
	public String blockFriendship(@PathVariable int friendID, Model model) {
		return blockFriendshipHandler(friendID, model, true);
	}
	
	@RequestMapping(value="/unblock/{friendID}")
	public String unblockFriendship(@PathVariable int friendID, Model model) {
		return blockFriendshipHandler(friendID, model, false);
	}
	
	/**
	 * handler for block and unblock methods
	 */
	private String blockFriendshipHandler(int friendID, Model model, boolean block) {
		User user = getAuthenticatedUser();
		User friend = userService.findByID(friendID);
		Friendship friendship = friendshipService.getFriendship(user, friend);
		
		try {
			friendshipService.blockFriendship(friendship, block);
			
			if(block)
				showFrontendMessage("friendshipBlockSuccess", friendship.getFriend().getFullName());
			else
				showFrontendMessage("friendshipUnblockSuccess", friendship.getFriend().getFullName());
		}
		catch(ServiceException e) {
			showFrontendMessage(e.getMessage(), SessionMessage.MessageType.WARNING, friend.getFullName());
		}
		
		return "redirect:/friends/info/"+friend.getId();
	}
	
	@RequestMapping(value="/request/new/{userID}")
	public String newFriendshipRequest(@PathVariable int userID, Model model) {
		User user = getAuthenticatedUser();
		User friend = userService.findByID(userID);
		
		try {
			Friendship friendship = friendshipService.requestFriendship(user, friend);
			showFrontendMessage("friendshipRequestSuccess", friend.getFullName());
			
			// friendship request successful, sent a confirmation mail
			Map<String, Object> mailData = new HashMap<String, Object>();
			mailData.put("friendship", friendship);
			mailService.sendMessage(friend.getEmail(), 
					getMessage("mailSubjectFriendshipRequest", user.getFullName()), 
					"friendshipRequest", 
					mailData);
		}
		catch(ServiceException e) {
			showFrontendMessage(e.getMessage(), SessionMessage.MessageType.WARNING, friend.getFullName());
		}
		
		return "redirect:/friends";
	}
	
	@RequestMapping(value="/confirm/{friendshipID}")
	public String confirmFriendShipRequest(@PathVariable int friendshipID, Model model) {
		User user = getAuthenticatedUser();
		Friendship friendshipReq = friendshipService.getFriendshipByID(friendshipID);
		
		try {
			Friendship newFriendship = friendshipService.confirmFriendship(user, friendshipReq);
			showFrontendMessage("friendshipConfirmSuccess", newFriendship.getFriend().getFullName());
			
			// friendship request successful, send a confirmation mail
			Map<String, Object> mailData = new HashMap<String, Object>();
			mailData.put("friendship", newFriendship);
			mailService.sendMessage(newFriendship.getFriend().getEmail(), 
					getMessage("mailSubjectFriendshipConfirmed", user.getFullName()), 
					"friendshipConfirmed", 
					mailData);
		}
		catch(ServiceException e) {
			showFrontendMessage(e.getMessage(), SessionMessage.MessageType.WARNING, 
					friendshipReq.getUser().getFullName());
		}
		
		return "redirect:/friends";
	}
	
	@RequestMapping(value="/cancel/{userID}")
	public String cancelFriendship(@PathVariable int userID, Model model) {
		User user = getAuthenticatedUser();
		User friend = userService.findByID(userID);
		
		try {
			friendshipService.cancelFriendship(user, friend);
			showFrontendMessage("friendshipCancelSuccess", friend.getFullName());
		}
		catch(ServiceException e) {
			showFrontendMessage(e.getMessage(), SessionMessage.MessageType.WARNING, friend.getFullName());
		}
		
		return "redirect:/friends";
	}
	
	@RequestMapping(value="/user/find")
	public String findNewFriends(@RequestParam(required=false) String search, Model model) {
		if(search != null) {
			List<User> users = userService.findByName(search);
			model.addAttribute("search", search);
			model.addAttribute("users", users);
		}
		return "/friends/userfind";
	}
	
	@RequestMapping(value="/user/info/{userID}")
	public String userInfo(@PathVariable int userID, Model model) {
		User user = userService.findByID(userID);
		model.addAttribute("user", user);
		return "/friends/userinfo";
	}
	
	@RequestMapping(value="/showfriendsajax")
	public String showFriendsAjax(Model model) {
		User user = getAuthenticatedUser();

		FriendshipStatus fsStatus = FriendshipStatus.ACTIVE;
		
		List<Friendship> friendships;
		
		friendships = friendshipService.getFriendships(user, fsStatus);
		
		model.addAttribute("friends", friendships);
		return "/friends/ajax_friends";
	}
}
